const https = require('https');
const axios = require('axios');
const fs = require('fs');
const path = require('path');
let year = 2025;
let month = 9;
let day = 1;
// 定义重试次数和重试间隔（毫秒）
const MAX_RETRIES = 3;
const RETRY_DELAY = 2000; // 2秒
const range = (start, stop, step = 1) =>
    Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + i * step);

const getUrl = (month, day) => {
    const monthstr = month < 10 ? `0${month}` : month;
    const daystr = day < 10 ? `0${day}` : day;
    // 建议将 t 参数设置为动态的，或者去掉，以防服务器缓存
    const url = `http://www.81.cn/_szb/jfjb/2025/${monthstr}/${daystr}/index.json?t=${Date.now()}`;
    return url;
};

/**
 * 延迟函数，用于重试间隔
 * @param {number} ms - 延迟的毫秒数
 */
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

/**
 * 下载文件的函数，带有重试机制
 * @param {string} url - 文件的URL
 * @param {string} filepath - 本地保存路径
 * @param {number} retries - 当前剩余的重试次数
 */
const download = async (url, filepath, retries = MAX_RETRIES) => {
    // 如果已存在，则跳过（可选功能）
    if (fs.existsSync(filepath)) {
        console.log(`文件已存在，跳过: ${filepath}`);
        return;
    }

    for (let attempt = 1; attempt <= retries; attempt++) {
        try {
            console.log(`正在下载 (尝试 ${attempt}/${retries}): ${url}`);
            
            // 确保目录存在
            fs.mkdirSync(path.dirname(filepath), { recursive: true });

            const fileStream = fs.createWriteStream(filepath);

            await new Promise((resolve, reject) => {
                const request = https.get(url, (response) => {
                    // 如果请求成功，则将响应流写入文件
                    if (response.statusCode === 200) {
                        response.pipe(fileStream);
                        fileStream.on('finish', resolve);
                    } else {
                        // 如果状态码不是200，认为是失败
                        reject(new Error(`下载失败，状态码: ${response.statusCode}`));
                    }
                });

                // 处理请求本身的错误，如 DNS 解析失败、连接超时等
                request.on('error', (err) => {
                    fileStream.destroy(); // 关闭并删除创建的空文件
                    reject(err);
                });

                // 处理文件写入错误
                fileStream.on('error', (err) => {
                    fileStream.destroy();
                    reject(err);
                });
            });

            console.log(`下载成功: ${filepath}`);
            return; // 成功则退出函数

        } catch (err) {
            // 如果失败且还有重试次数，则等待后重试
            if (attempt < retries) {
                console.log(`下载失败: ${err.message}。将在 ${RETRY_DELAY / 1000} 秒后重试...`);
                await delay(RETRY_DELAY);
            } else {
                // 如果达到最大重试次数仍失败，则抛出最终错误
                console.error(`所有重试均失败 for ${url}`);
                // 尝试删除可能不完整的文件
                if (fs.existsSync(filepath)) {
                    fs.unlinkSync(filepath);
                }
                throw err; // 将错误向上抛出，中断整个任务或让调用者处理
            }
        }
    }
};

async function main() {
    try {
        const lastDayOfMonth = new Date(year, month - 1, 0);
        const days = range(day, lastDayOfMonth.getDate());
        // 使用 for...of 循环来顺序处理，更好地支持 async/await
        for (let day of days) {
            const dir = path.resolve(__dirname, `./downloads/${year}-${month}.${day}`);
            const url = getUrl(month, day);
            console.log(`\n--- 正在处理日期: ${year}-${month}-${day} ---`);

            let res;
            try {
                // 对获取 index.json 的请求也增加简单的重试
                res = await axios.get(url);
            } catch (axiosErr) {
                console.error(`获取索引文件 ${url} 失败: ${axiosErr.message}`);
                continue; // 如果索引都拿不到，就跳过这个日期
            }

            const paperInfoList = res.data.paperInfo;
            if (!paperInfoList || paperInfoList.length === 0) {
                console.log(`未找到 PDF 文件信息。`);
                continue;
            }

            console.log(`找到 ${paperInfoList.length} 个 PDF 文件，开始下载...`);

            for (const item of paperInfoList) {
                const file = path.resolve(dir, `${item.paperNumber}.pdf`);
                try {
                    await download(item.paperPDF, file);
                    await delay(4000);
                } catch (downloadErr) {
                    console.error(`下载 ${item.paperPDF} 时发生致命错误: ${downloadErr.message}`);
                    // 你可以选择在这里 'continue' 跳过这个文件，或者 'break' 停止整个任务
                    // 目前选择继续处理下一个文件
                }
            }
        }
        console.log('\n所有任务处理完毕。');
    } catch (mainErr) {
        console.error(`主程序发生未预料的错误: ${mainErr.message}`);
    }
}

main();